package com.itheima.cs.common.wwdb;

import android.Manifest;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.print.PrintAttributes;
import android.print.PrintDocumentAdapter;
import android.print.PrintManager;
import android.provider.Settings;
import android.util.Log;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.itheima.cs.R;
import com.itheima.cs.dao.UserDao;
import com.itheima.cs.dao.dbd.InternalTransferDao;
import com.itheima.cs.dao.dbd.WarehouseDao;
import com.itheima.cs.entity.Userinfo;
import com.itheima.cs.entity.dbd.InternalTransfer;
import com.itheima.cs.entity.dbd.WarehouseInfo;
import com.itheima.cs.utils.EscCommand;
import com.itheima.cs.utils.MyApplication;
import com.yingmei.printsdk.JolimarkPrint;
import com.yingmei.printsdk.bean.DeviceInfo;
import com.yingmei.printsdk.bean.PrintCallback;
import com.yingmei.printsdk.bean.PrintParameters;
import com.yingmei.printsdk.bean.SearchCallback;
import com.yingmei.printsdk.bean.TransType;
import com.yingmei.printsdk.core.States;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;

import java.util.HashSet;
import java.util.List;

import java.util.Set;

public class OutsourcingAllocationDetailActivity extends AppCompatActivity {

    private WebView webView;
    private InternalTransfer currentTransfer;

    private TextView tvTransferNumber, tvOutName, tvInName, tvFwcmPers;
    private TextView tvMaterialCode, tvMaterialName, tvMaterialSpec, tvDate;
    private TextView tvQuantity, tvUserName;

    private Handler printTimeoutHandler = new Handler();

    private AlertDialog printerDialog;

    private final HashSet<String> deviceMacSet = new HashSet<>();

    private static final int PRINT_TIMEOUT = 3000;

    private final Set<String> SUPPORTED_PRINTERS = new HashSet<>(Arrays.asList(
            "CLP-180", "JPM-100", "JPM-200"
    ));

    private static final String TAG = "PrinterHandler";
    private static final String WORKSHOP_PRINTER_NAME = "车间打印机";

    private final ArrayList<DeviceInfo> discoveredPrinters = new ArrayList<>();
    private boolean isSearching = false;
    private final Handler searchHandler = new Handler();
    private static final int SEARCH_INTERVAL = 10000;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_outsourcing_allocation_detail);

        int localId = getIntent().getIntExtra("localId", -1);
        initViews();
        setupToolbar();
        setupPrintWebView();
        loadData(localId);
        startPrinterDiscovery();
    }

    private void initViews() {
        tvTransferNumber = findViewById(R.id.tv_transfer_number);
        tvOutName = findViewById(R.id.tv_out_name);
        tvInName = findViewById(R.id.tv_in_name);
        tvFwcmPers = findViewById(R.id.tv_fwcmpers);
        tvMaterialCode = findViewById(R.id.tv_material_code);
        tvMaterialName = findViewById(R.id.tv_material_name);
        tvMaterialSpec = findViewById(R.id.tv_material_spec);
        tvDate = findViewById(R.id.tv_date);
        tvQuantity = findViewById(R.id.et_quantity);
        tvUserName = findViewById(R.id.tv_user_name);

        findViewById(R.id.btn_print).setOnClickListener(v -> printDocument());
    }

    private void setupToolbar() {
        Toolbar toolbar = findViewById(R.id.toolbar_add_outsourcing_allocation_detail);
        setSupportActionBar(toolbar);
        toolbar.setNavigationOnClickListener(v -> finish());
    }

    private void setupPrintWebView() {
        webView = new WebView(this);
        webView.setWebViewClient(new WebViewClient() {
            public void onPageFinished(WebView view, String url) {
                createPrintJob();
            }
        });
    }

    private void loadData(int localId) {
        ProgressDialog loadingDialog = new ProgressDialog(this);
        loadingDialog.setMessage("加载数据中...");
        loadingDialog.setCancelable(false);
        loadingDialog.show();

        new Thread(() -> {
            try {
                currentTransfer = new InternalTransferDao().getTransferById(localId);

                if (currentTransfer != null) {
                    WarehouseInfo warehouse = new WarehouseDao().getByNumber(currentTransfer.getInWarehouseNo(),"3");
                    if (warehouse != null) {
                        currentTransfer.setFwcmPers(warehouse.getFwcmPers());
                    }
                    Userinfo user = new UserDao().getUserById(Integer.parseInt(currentTransfer.getUserId()));

                    runOnUiThread(() -> {
                        loadingDialog.dismiss();
                        if (currentTransfer != null) {
                            updateUI(currentTransfer);
                            if (user != null) {
                                tvUserName.setText(user.getName());
                            }
                            if (warehouse != null) {
                                tvFwcmPers.setText(currentTransfer.getFwcmPers());
                            }
                        }
                    });
                }
            } catch (Exception e) {
                e.printStackTrace();
                runOnUiThread(() -> {
                    loadingDialog.dismiss();
                    Toast.makeText(this, "数据加载失败", Toast.LENGTH_SHORT).show();
                });
            }
        }).start();
    }

    private void updateUI(InternalTransfer transfer) {
        tvTransferNumber.setText(transfer.getTransferNumber() != null ? transfer.getTransferNumber() : "N/A");
        tvOutName.setText(transfer.getOutWarehouseName() != null ? transfer.getOutWarehouseName() : "N/A");
        tvInName.setText(transfer.getInWarehouseName() != null ? transfer.getInWarehouseName() : "N/A");
        tvFwcmPers.setText(transfer.getFwcmPers() != null ? transfer.getFwcmPers() : "N/A");
        tvMaterialCode.setText(transfer.getMaterialCode() != null ? transfer.getMaterialCode() : "N/A");
        tvMaterialName.setText(transfer.getMaterialName() != null ? transfer.getMaterialName() : "N/A");
        tvMaterialSpec.setText(transfer.getMaterialSpec() != null ? transfer.getMaterialSpec() : "N/A");
        tvQuantity.setText(transfer.getEtQuantity() != null ? transfer.getEtQuantity() : "N/A");
        tvDate.setText(transfer.getDate() != null ? transfer.getDate() : "N/A");
    }



    private void startPrinterDiscovery() {
        if (!checkBluetoothPermissions()) {
            requestBluetoothPermissions();
            return;
        }

        if (!isSearching) {
            isSearching = true;
            scheduleNextSearch();
        }
    }

    private void scheduleNextSearch() {
        searchHandler.postDelayed(() -> {
            if (!isSearching) return;

            JolimarkPrint.searchDevices(this, 3000, TransType.TRANS_ALL, new SearchCallback() {
                @Override
                public void startDevices() {
                    runOnUiThread(() -> Log.d("PrinterSearch", "开始搜索打印机..."));
                }

                @Override
                public void stopDevices(List<DeviceInfo> devices) {
                    runOnUiThread(() -> Log.d("PrinterSearch", "本次搜索结束，找到设备：" + discoveredPrinters.size()));
                    scheduleNextSearch();
                }

                @Override
                public void findDevices(DeviceInfo deviceInfo) {
                    handleNewDevice(deviceInfo);
                }
            });
        }, SEARCH_INTERVAL);
    }

    private String extractUniqueId(DeviceInfo device) {
        String did = device.getDid();

        if (did.startsWith("CLP-180-")) {
            return did.substring(8);
        } else if (did.matches("^\\d+[A-Z]+$")) {
            return did;
        }
        return did;
    }



    private String getDisplayName(DeviceInfo device) {
        String did = device.getDid();
        for (String model : SUPPORTED_PRINTERS) {
            if (did.startsWith(model + "-") || did.matches("^\\d+[A-Z]+$")) {
                return WORKSHOP_PRINTER_NAME + getConnectionType(device);
            }
        }
        return did;
    }

    private void handleNewDevice(DeviceInfo deviceInfo) {
        String uniqueId = extractUniqueId(deviceInfo);
        String connectionType = getConnectionType(deviceInfo);

        synchronized (deviceMacSet) {
            if (!deviceMacSet.contains(uniqueId)) {
                deviceMacSet.add(uniqueId);
                discoveredPrinters.add(deviceInfo);
                Log.d(TAG, "发现新设备: " + deviceInfo.getDid()
                        + " | 类型: " + connectionType
                        + " | 统一标识: " + uniqueId);
            }
        }
    }


    private String getConnectionType(DeviceInfo device) {

        String did = device.getDid();
        if (did.contains("BLUETOOTH") || did.startsWith("CLP-180")) {
            return "（蓝牙）";
        } else if (did.contains("WIFI") || did.matches("^\\d+[A-Z]+$")) {
            return "（WiFi）";
        }
        return "";
    }
    private void printDocument() {
        List<DeviceInfo> printers = MyApplication.getInstance().getPrinters();

        if (printers.isEmpty()) {
            showSearchStatus();
        } else {
            showPrinterSelection(printers);
        }
    }

    private void showSearchStatus() {
        new AlertDialog.Builder(this)
                .setTitle("打印机搜索状态")
                .setMessage(MyApplication.getInstance().isSearching() ?
                        "正在搜索打印机，请稍候..." :
                        "未找到可用打印机\n可能原因：\n1. 打印机未开机\n2. 网络未连接")
                .setPositiveButton("刷新", (d, w) -> refreshPrinters())
                .setNegativeButton("取消", null)
                .show();
    }

    private void refreshPrinters() {
        MyApplication.getInstance().startGlobalSearch();
        printDocument();
    }

    private void showPrinterSelection(List<DeviceInfo> printers) {
        List<String> nameList = new ArrayList<>();
        Set<String> addedIds = new HashSet<>();

        for (DeviceInfo device : printers) {
            String uniqueId = extractUniqueId(device);
            if (!addedIds.contains(uniqueId)) {
                nameList.add(getDisplayName(device));
                addedIds.add(uniqueId);
            }
        }

        String[] names = nameList.toArray(new String[0]);

        printerDialog = new AlertDialog.Builder(this)
                .setTitle("选择打印机（共" + nameList.size() + "台）")
                .setItems(names, (d, which) -> {
                    String selectedName = names[which];
                    List<DeviceInfo> matchedDevices = new ArrayList<>();
                    for (DeviceInfo device : printers) {
                        if (getDisplayName(device).equals(selectedName)) {
                            matchedDevices.add(device);
                        }
                    }

                    if (!matchedDevices.isEmpty()) {
                        executePrint(matchedDevices.get(0));
                    }
                })
                .setOnDismissListener(d -> printerDialog = null)
                .show();
    }
    private DeviceInfo findFirstDeviceByDisplayName(String displayName, List<DeviceInfo> devices) {
        for (DeviceInfo device : devices) {
            if (getDisplayName(device).equals(displayName)) {
                return device;
            }
        }
        return null;
    }


    private boolean checkBluetoothPermissions() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            return ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                    == PackageManager.PERMISSION_GRANTED
                    && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_WIFI_STATE)
                    == PackageManager.PERMISSION_GRANTED;
        }
        return true;
    }

    @Override
    protected void onPause() {
        super.onPause();
        isSearching = false;
        searchHandler.removeCallbacksAndMessages(null);
        JolimarkPrint.stopSearch(false);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (!isSearching) {
            startPrinterDiscovery();
        }
    }


    private final ArrayList<DeviceInfo> deviceList = new ArrayList<>();

    private void showPrinterSelectionDialog(List<DeviceInfo> devices) {
        if (devices == null || devices.isEmpty()) {
            new AlertDialog.Builder(this)
                    .setTitle("提示")
                    .setMessage("未找到可用打印机")
                    .setPositiveButton("重试", (d, w) -> printDocument())
                    .setNegativeButton("取消", null)
                    .show();
            return;
        }

        List<String> nameList = new ArrayList<>();
        for (DeviceInfo device : devices) {
            nameList.add(device.getDid());
        }
        String[] names = nameList.toArray(new String[0]);

        new AlertDialog.Builder(this)
                .setTitle("选择打印机")
                .setItems(names, (dialog, which) -> {
                    DeviceInfo selected = devices.get(which);
                    executePrint(selected);
                })
                .show();
    }



    private void requestBluetoothPermissions() {
        List<String> permissions = new ArrayList<>();

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            permissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
        }

        if (getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.P) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.CHANGE_WIFI_MULTICAST_STATE) != PackageManager.PERMISSION_GRANTED) {
                permissions.add(Manifest.permission.CHANGE_WIFI_MULTICAST_STATE);
            }
        }

        if (!permissions.isEmpty()) {
            ActivityCompat.requestPermissions(
                    this,
                    permissions.toArray(new String[0]),
                    1001
            );
        } else {
            printDocument();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (requestCode == 1001) {
            boolean allGranted = true;
            for (int result : grantResults) {
                if (result != PackageManager.PERMISSION_GRANTED) {
                    allGranted = false;
                    break;
                }
            }

            if (allGranted) {
                startPrinterDiscovery();
            } else {
                new AlertDialog.Builder(this)
                        .setTitle("权限不足")
                        .setMessage("需要位置权限来发现附近的打印机")
                        .setPositiveButton("去设置", (d, w) -> openAppSettings())
                        .setNegativeButton("取消", null)
                        .show();
            }
        }
    }

    private String getPermissionName(String permission) {
        switch (permission) {
            case Manifest.permission.ACCESS_FINE_LOCATION:
                return "定位权限（用于设备搜索）";
            case Manifest.permission.ACCESS_WIFI_STATE:
                return "WiFi状态权限";
            case Manifest.permission.CHANGE_WIFI_MULTICAST_STATE:
                return "WiFi多播权限";
            default:
                return "未知权限";
        }
    }

    private void openAppSettings() {
        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        intent.setData(Uri.parse("package:" + getPackageName()));
        startActivity(intent);
    }






    private byte[] generateEscPosData() {
        if (currentTransfer == null) return new byte[0];

        ArrayList<byte[]> commands = new ArrayList<>();

        // ================ 第一联：调入仓库联 ================
        printTransferDocument(commands, true);

        // ================ 第二联：调出仓库联 ================
        printTransferDocument(commands, false);

        // 合并指令
        return mergeByteArrays(commands);
    }

    private void printTransferDocument(ArrayList<byte[]> commands, boolean isInWarehouse) {
        // 初始化打印机
        commands.add(EscCommand.INIT);

        // ======= 抬头标识 =======
        // 设置绝对打印位置（单位：dots）
        int xPosition = isInWarehouse ? 130 : 430; // 根据打印机分辨率调整
        byte[] positionCmd = new byte[]{
                0x1B, 0x24,
                (byte) (xPosition % 256),
                (byte) (xPosition / 256)
        };
        commands.add(positionCmd);

        // 打印带边框的标识
        commands.add(EscCommand.stringToByte("┏━━━━━━━┓\n"));
        commands.add(positionCmd);
        commands.add(new byte[]{0x1B, 0x21, 0x08}); // 加粗
        commands.add(EscCommand.stringToByte(
                isInWarehouse ? "┃ 调出仓库持有 ┃\n" : "┃ 调入仓库持有 ┃\n"
        ));
        commands.add(new byte[]{0x1B, 0x21, 0x00}); // 取消加粗
        commands.add(positionCmd);
        commands.add(EscCommand.stringToByte("┗━━━━━━━┛\n\n"));



        // 设置标题格式
        // 设置居中
        commands.add(EscCommand.ESC_ALIGN_CENTER);
        commands.add(EscCommand.ESC_ALIGN_CENTER);
        commands.add(EscCommand.BGK); // 倍高倍宽
        commands.add(EscCommand.stringToByte("内部调拨单\n\n"));
        commands.add(EscCommand.UBGK); // 取消倍高倍宽


        // ======= 主体内容 =======
        // 设置左边距
        int leftMargin = 20; // mm
        int dots = leftMargin * 8;
        commands.add(new byte[]{
                0x1D, 0x4C,
                (byte) (dots % 256),
                (byte) (dots / 256)
        });

        // 基础信息
        String[] contents = {
                "调拨单号：" + currentTransfer.getTransferNumber(),
                "调出仓库：" + currentTransfer.getOutWarehouseName(),
                "调入仓库：" + currentTransfer.getInWarehouseName(),
                "调入仓库审核员：" + currentTransfer.getFwcmPers(),
                "物料编码：" + currentTransfer.getMaterialCode(),
                "物料名称：" + currentTransfer.getMaterialName(),
                "规格型号：" + currentTransfer.getMaterialSpec(),
                "调拨数量：" + currentTransfer.getEtQuantity(),
                "日期：" + currentTransfer.getDate(),
                "操作员：" + tvUserName.getText().toString()
        };

        // 打印内容
        commands.add(EscCommand.ESC_ALIGN_LEFT);
        for (String line : contents) {
            commands.add(EscCommand.stringToByte(line + "\n"));
        }

        // 分隔线
        commands.add(EscCommand.stringToByte("--------------------------------\n"));

        // 走纸3行
        commands.add(new byte[]{0x1B, 0x64, 0x03});

        // 切纸（根据打印机支持情况）
        if (!isInWarehouse) {
            commands.add(new byte[]{0x1D, 0x56, 0x42, 0x00}); // 全切
        }
    }

    private byte[] mergeByteArrays(List<byte[]> arrays) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            for (byte[] array : arrays) {
                outputStream.write(array);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return outputStream.toByteArray();
    }

    // 修改后的executePrint方法
    private void executePrint(DeviceInfo device) {
        ProgressDialog printDialog = new ProgressDialog(this);
        printDialog.setMessage("准备打印中...");
        printDialog.setCancelable(false);
        printDialog.show();

        // 创建超时检测任务
        Runnable timeoutTask = new Runnable() {
            @Override
            public void run() {
                if (!isFinishing() && printDialog.isShowing()) {
                    printDialog.dismiss();
                    handlePrintTimeout(device);
                }
            }
        };

        // 生成ESC指令数据
        byte[] escData = generateEscPosData();

        PrintParameters params = new PrintParameters();
        params.ptype = 0; // 打印类型
        params.printType = PrintParameters.PT_THERMAL;
        params.printModel = "CLP-180"; // 根据实际打印机型号修改
        params.data = escData; // 使用ESC指令数据
        params.paper_width = 80;
        params.paper_type = 1;

        // 启动超时检测
        printTimeoutHandler.postDelayed(timeoutTask, PRINT_TIMEOUT);

        JolimarkPrint.sendToData(this, device, params, new PrintCallback() {
            @Override
            public void printResult(int state, String taskId, String msg) {

                // 移除未触发的超时任务
                printTimeoutHandler.removeCallbacks(timeoutTask);

                runOnUiThread(() -> {
                    printDialog.dismiss();
                    handlePrintResult(state, msg, device);
                });
            }

            @Override
            public void onReceiveData(int cmd, byte[] data) {
                Log.d("PrintFlow", "Received data - CMD:" + cmd + " Length:" + (data != null ? data.length : 0));
            }
        });
    }

    private void handlePrintTimeout(DeviceInfo device) {
        new AlertDialog.Builder(this)
                .setTitle("打印超时")
                .setMessage("无法连接到打印机，请检查：\n" +
                        "1. 打印机是否已开机\n" +
                        "2. 设备是否在同一个网络\n" +
                        "3. 打印机是否支持当前格式")
                .setPositiveButton("重试", (d, w) -> executePrint(device))
                .setNegativeButton("取消", null)
                .show();
    }

    // 处理打印结果
    private void handlePrintResult(int state, String msg, DeviceInfo device) {
        if (state == States.OK) {
            Toast.makeText(this, "打印任务已发送", Toast.LENGTH_SHORT).show();
        } else {
            new AlertDialog.Builder(this)
                    .setTitle("打印失败")
                    .setMessage(getErrorMessage(state, msg))
                    .setPositiveButton("重试", (d, w) -> executePrint(device))
                    .setNegativeButton("取消", null)
                    .show();
        }
    }

    // 获取友好错误信息
    private String getErrorMessage(int errorCode, String defaultMsg) {
        switch (errorCode) {
            case PrintStates.ERR_CONNECT:
                return "打印机连接失败，请检查设备是否开启";
            case PrintStates.ERR_IO:
                return "通信异常，请检查连接状态";
            case PrintStates.ERR_PAPER:
                return "打印机缺纸，请装入纸张";
            case PrintStates.ERR_HEAT:
                return "打印头过热，请稍后重试";
            default:
                return "错误码：" + errorCode + "\n错误信息：" + defaultMsg;
        }
    }

    public class PrintStates {
        public static final int OK = 0;
        public static final int ERR_CONNECT = -1;   // 连接错误
        public static final int ERR_IO = -2;        // 通信错误
        public static final int ERR_PAPER = -3;     // 缺纸错误
        public static final int ERR_HEAT = -4;      // 打印头过热
    }

    private void createPrintJob() {
        PrintManager printManager = (PrintManager) getSystemService(PRINT_SERVICE);
        try {
            PrintDocumentAdapter printAdapter = webView.createPrintDocumentAdapter("TransferDocument");
            String jobName = "调拨单_" + currentTransfer.getTransferNumber();
            printManager.print(jobName, printAdapter, new PrintAttributes.Builder().build());
        } catch (Exception e) {
            Toast.makeText(this, "打印失败: " + e.getMessage(), Toast.LENGTH_LONG).show();
        }
    }

    @Override
    protected void onDestroy() {
        if (webView != null) {
            webView.destroy();
        }
        super.onDestroy();
    }
}
